package cn.wyd.shield.token.jwt;



import cn.wyd.shield.token.jwt.exception.TokenExpire;
import cn.wyd.shield.token.jwt.exception.TokenIsChange;
import com.alibaba.fastjson.JSON;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;

public class JwtUtil {
    private static Base64.Encoder encoder =  Base64.getUrlEncoder();
    private static Base64.Decoder decoder = Base64.getUrlDecoder();
    public static String secret = "wyd";
    private static Mac sha256_HMAC = null;
    static {
        try {
            sha256_HMAC = Mac.getInstance("HmacSHA256");
            SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
            sha256_HMAC.init(secret_key);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }
    public static JwtToken authen(String token) throws InvalidKeyException, NoSuchAlgorithmException, TokenIsChange {
        //Base64.Decoder decoder =  Base64.getUrlDecoder();
       try{
           if(token==null){
               throw  new TokenIsChange("token为空");
           }

           String playLoad = token.substring(0,token.indexOf("."));
           String tokenstr = token.substring(token.lastIndexOf(".")+1,token.length());
           if(isBlank(playLoad)){
               throw  new TokenIsChange("playLoad为空");
           }
           if(isBlank(secret)){
               throw  new TokenIsChange("secret为空");
           }
           checkSign(playLoad,tokenstr,JwtUtil.secret);
           JwtToken jwtToken = decoder64(playLoad);
           checkToken(jwtToken);
           return jwtToken;
       }catch (StringIndexOutOfBoundsException e){
           throw  new TokenIsChange("token格式错误");
       }

    }

    private static Boolean isBlank(String str){
        if(str == null || str.equals("")){
            return true;
        }else{
            return false;
        }
    }


    public static String encode(String playload){
        return new String(encoder.encode(playload.getBytes()));
    }

    public static String build(String toPlayLoadString,String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        String pstr = encode(toPlayLoadString);
        String hash = encodeBase64(pstr,secret);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(pstr+".").append(hash);
        return stringBuilder.toString();
    }

    public static String encodeBase64(String playload64,String secret) throws NoSuchAlgorithmException, InvalidKeyException {
        String hash = new String(encoder.encode((sha256_HMAC.doFinal((playload64).getBytes()))));
        return hash;
    }

    public static void checkSign(String pstr,String token,String secret) throws NoSuchAlgorithmException, InvalidKeyException, TokenIsChange {
        String cStr = encodeBase64(pstr,secret);
        if(!cStr.equals(token)){
            throw new TokenIsChange("错误的凭证");
        }
    }

    public static void checkToken(JwtToken jwtToken)  {
       // System.out.println(new Date(jwtToken.getExp()*1000));
        if(jwtToken.getExp()<System.currentTimeMillis()/1000){
            throw new TokenExpire("token已过期");
        }
    }

    public static String buildToken(String uid, String  name) throws InvalidKeyException, NoSuchAlgorithmException {
        JwtToken jwtToken = new JwtToken(uid,name);
        return  build(jwtToken.toPlayLoadString(),secret);
    }


    public static JwtToken decoder64(String str){
        String decString = new String(decoder.decode(str));
        JwtToken jwtToken = JSON.parseObject(decString,JwtToken.class);
        return jwtToken;
    }


    public static JwtToken decoder64(HttpServletRequest request){
        String token = request.getHeader("auth");
        String playLoad = token.substring(0,token.indexOf("."));
        String decString = new String(decoder.decode(playLoad));
        JwtToken jwtToken = JSON.parseObject(decString,JwtToken.class);
        return jwtToken;
    }

}
